package com.foreveross.crawl.common.application;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Logger;
import org.dayatang.domain.InstanceFactory;
import org.dayatang.querychannel.QueryChannelService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.foreveross.GlobalMapOperator;
import com.foreveross.crawl.common.core.TaskModelEntity;
import com.foreveross.crawl.common.em.TaskState;
import com.foreveross.crawl.common.exception.BusinessException;
import com.foreveross.crawl.common.exception.TaskStateException;
import com.foreveross.crawl.common.util.DateUtil;
import com.foreveross.crawl.common.util.StringUtils;
import com.foreveross.crawl.dto.TaskModelDto;
import com.foreveross.crawl.vo.TaskStatisticsVO;

@Service
@Transactional
public class TaskModelEntityApplicationImpl implements ITaskModelEntityApplication {

	private Logger logger = Logger.getLogger(TaskModelEntityApplicationImpl.class);
	
	private QueryChannelService queryChannelService;
	
	private final String split= "####";
	
	public QueryChannelService getQueryChannelService() {
		if (queryChannelService == null) {
			queryChannelService = InstanceFactory.getInstance(QueryChannelService.class, "queryChannel_ss");
		}
		return queryChannelService;
	}

	
	@Override
	public List<TaskModelDto> getTaskModelByTaskId(String taskId) {

		List<TaskModelEntity> entityList = TaskModelEntity.findByTaskId(taskId);
		return domainListToDtoList(entityList);
	}

	private List<TaskModelDto> domainListToDtoList(List<TaskModelEntity> entityList) {
		List<TaskModelDto> retList = new ArrayList<TaskModelDto>();
		for(TaskModelEntity entity : entityList){
			retList.add(this.domainToDto(entity));
		}
		return retList;
	}
	
	private TaskModelEntity dtoToDomain(TaskModelDto dto){
		TaskModelEntity domain = new TaskModelEntity();
		try {
			BeanUtils.copyProperties(domain, dto);
			domain.setId(null);
			domain.setTaskId(dto.getId());
			List<String> tracks = dto.getTracksList();
			if(tracks != null && tracks.size() != 0){
				StringBuffer sb = new StringBuffer("");
				for(String track : tracks){
					sb.append(track).append(split);
				}
				domain.setTracks(StringUtils.stringToClob(sb.toString()));
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
		return domain;
	}
	
	private TaskModelDto domainToDto(TaskModelEntity domain){
		
		TaskModelDto dto = new TaskModelDto();
		List<String> trackList = new ArrayList<String>();
		try {
			BeanUtils.copyProperties(dto, domain);
			dto.setId(domain.getTaskId());
			String tracks = StringUtils.clobToString(domain.getTracks());
			if(tracks != null && !tracks.equals("")){
				for(String track : tracks.split(split)){
					if(track != null && !track.trim().equals(""))
						trackList.add(track);
				}
			}
			dto.setTracksList(trackList);
		} catch (Exception e) {
			logger.error("对象复制失败:" + e.getMessage());
		} 
		return dto;
	}

	@Override
	public List<TaskModelDto> getTaskModelByChannelId(Long channelId) {

		List<TaskModelEntity> entityList = TaskModelEntity.findByProperty(TaskModelEntity.class, "channelId", channelId);
		return domainListToDtoList(entityList);
	}
	
	@SuppressWarnings("unchecked")
	public List<TaskModelDto> getTaskModelByChannelIdAndState(Long channelId, String state){
		List<TaskModelEntity> entityList = null;
		StringBuffer sb = new StringBuffer();
		sb.append("select t from TaskModelEntity t where 1 = 1 ");
		if(state.equalsIgnoreCase("ALL") && channelId != null){
//			entityList = TaskModelEntity.findByProperty(TaskModelEntity.class, "channelId", channelId);
			sb.append(" and t.channelId =:channelId order by t.id desc");
			entityList = this.getQueryChannelService().createJpqlQuery(sb.toString()).addParameter("channelId", channelId).list();
		} else if(state.equalsIgnoreCase("ALL") && channelId == null){
//			entityList = TaskModelEntity.findAll(TaskModelEntity.class);
			sb.append(" order by t.id desc");
			entityList = this.getQueryChannelService().createJpqlQuery(sb.toString()).list();
		} else if(channelId == null){
//			entityList = TaskModelEntity.findByProperty(TaskModelEntity.class, "taskState", state);
			sb.append(" and t.taskState =:taskState order by t.id desc");
			entityList = this.getQueryChannelService().createJpqlQuery(sb.toString()).addParameter("taskState", state).list();
		} else {
//			entityList = TaskModelEntity.findTaskModelByChannelIdAndState(channelId, state);
			sb.append(" and t.channelId =:channelId and t.taskState =:taskState order by t.id desc");
			entityList = this.getQueryChannelService().createJpqlQuery(sb.toString()).addParameter("channelId", channelId).addParameter("taskState", state).list();
		}
		
		return domainListToDtoList(entityList);
	}
	
	public int countTaskModelByChannelIdAndState(Long channelId, String state){
		List<TaskStatisticsVO> entityList = null;
		StringBuffer sb = new StringBuffer();
		sb.append("select NEW com.foreveross.crawl.vo.TaskStatisticsVO(count(t)) from TaskModelEntity t where 1 = 1 ");
		if(state.equalsIgnoreCase("ALL") && channelId != null){
			sb.append(" and t.channelId =:channelId");
			entityList = this.getQueryChannelService().createJpqlQuery(sb.toString()).addParameter("channelId", channelId).list();
		} else if(state.equalsIgnoreCase("ALL") && channelId == null){
			entityList = this.getQueryChannelService().createJpqlQuery(sb.toString()).list();
		} else if(channelId == null){
			sb.append(" and t.taskState =:taskState");
			entityList = this.getQueryChannelService().createJpqlQuery(sb.toString()).addParameter("taskState", state).list();
		} else {
			sb.append(" and t.channelId =:channelId and t.taskState =:taskState");
			entityList = this.getQueryChannelService().createJpqlQuery(sb.toString()).addParameter("channelId", channelId).addParameter("taskState", state).list();
		}
		
		return entityList == null ? 0 : entityList.get(0).getCount().intValue();
	}

	@Override
	public List<TaskModelDto> getAllTaskModel() {

		List<TaskModelEntity> entityList = TaskModelEntity.findAll(TaskModelEntity.class);
		return domainListToDtoList(entityList);
	}

	@Override
	public void addTaskModel(TaskModelDto dto) {

		TaskModelEntity entity = this.dtoToDomain(dto);
		entity.save();
	}

	@Override
	public void updateTaskState(String taskId, String state) throws TaskStateException {

		TaskModelEntity newest = getEntityById(taskId);
		newest.setTaskState(state);
		TaskModelEntity.saveOrUpdate(newest);
	}

	private TaskModelEntity getEntityById(String taskId)
			throws TaskStateException {
		TaskModelEntity newest = TaskModelEntity.findNewestByTaskId(taskId);
		if(newest == null)
			throw new TaskStateException("获取不到所需任务模型对象");
		return newest;
	}

	@Override
	public void updateTaskStartDate(String taskId, String dateStr) throws TaskStateException {

		TaskModelEntity newest = getEntityById(taskId);
		newest.setTaskStartDate(dateStr);
		TaskModelEntity.saveOrUpdate(newest);
	}

	@Override
	public void updateTaskEndDateAndExcuteTime(Long channelId, String taskId, long excuteTime,
			boolean isStateFinished) throws TaskStateException, BusinessException {

		TaskModelEntity newest = getEntityById(taskId);
		newest.setTaskEndDate(DateUtil.formatDay(new Date(), "HH时mm分ss秒"));
		newest.setTaskExcuteTotal(excuteTime);
		if(isStateFinished){
			newest.setTaskState(TaskState.FINISHED.getType());
			GlobalMapOperator.updateTaskSuccessNumber(channelId);
		}
		TaskModelEntity.saveOrUpdate(newest);
	}

	@Override
	public void recordTracksOfTask(String taskId, String track)
			throws TaskStateException {

		TaskModelEntity newest = getEntityById(taskId);
		StringBuffer sb = new StringBuffer("");
		String tracks = StringUtils.clobToString(newest.getTracks());
		if(tracks != null && !tracks.trim().equals("")){
			sb.append(StringUtils.clobToString(newest.getTracks())).append(split);
		}
		sb.append(DateUtil.formatDay(new Date(), "HH:mm:ss")).append(" ").append(track);
		newest.setTracks(StringUtils.stringToClob(sb.toString()));
		TaskModelEntity.saveOrUpdate(newest);
	}
	
	@Override
	public void deleteValidTaskModel() {
		
		TaskModelEntity.deleteTaskModelForValid();
	}

	@Override
	public void deleteAllTaskModel() {

		TaskModelEntity.deleteAll();
	}

	@Override
	public int countAllTaskModel() {

		return TaskModelEntity.countTaskModel();
	}

	@Override
	public int countSuccessTaskModel(Long channelId) {
		return TaskModelEntity.countTaskModelOfSuccess(channelId);
	}

	@Override
	public int countDoingTaskModel(Long channelId) {
		return TaskModelEntity.countTaskModelOfDoing(channelId);
	}

	@Override
	public int countException(Long channelId) {
		return TaskModelEntity.countTaskModelOfFail(channelId);
	}


	@SuppressWarnings("unchecked")
	@Override
	public List<TaskStatisticsVO> statisticsTask() {
		StringBuilder jpql = new StringBuilder("SELECT NEW com.foreveross.crawl.vo.TaskStatisticsVO(t.channelId, t.channelName, t.taskState, count(t.taskState)) from TaskModelEntity t group by t.channelId,t.channelName,t.taskState ");
		return getQueryChannelService().createJpqlQuery(jpql.toString()).list();
	}

}
